package pt.ipleiria.plp.Lixeiras;

import pt.ipleiria.plp.*;
import java.rmi.RemoteException;
import pt.ipleiria.plp.stub.ArrayOfBlackSpot;
import pt.ipleiria.plp.stub.ArrayOfMediaReader;
import pt.ipleiria.plp.stub.BlackSpot;
import pt.ipleiria.plp.stub.BlackSpotState;
import pt.ipleiria.plp.stub.OperationStatus;
import pt.ipleiria.plp.stub.SpottingSoap_Stub;

/**
 * Class containing the data of a lixeira already sent
 * @author Filipe Felisberto e Ricardo Silva
 */
public class LixeiraSent extends Lixeira {

    private transient BlackSpot bs;
    private transient ImageURL[] imagesURLs;
    private boolean synced;

    public LixeiraSent(String guid, String title, String state) {
        super(guid, title, state);
    }

    /**
     * Constructor that recieves its data from a blackspot recieved from the
     * webservice.
     * @param bs
     */
    public LixeiraSent(BlackSpot bs) {
        super(bs.getSpotId(), bs.getTitle(), bs.getStatus().getValue());
        this.bs = bs;
    }

    /**
     * Deletes this lixeira from the server
     * @param app the app key
     * @return null if it worked or the error message
     */
    public String delete(String app) {
        try {
            SpottingSoap_Stub service = new SpottingSoap_Stub();
            System.out.println("id-" + getGuid());
            System.out.println("app-" + app);
            OperationStatus ops = service.deleteBlackSpot(getGuid(), app);

            if (ops.isOperationSuceeded()) {
                return null;
            } else {
                return ops.getErrorMessage();
            }

        } catch (RemoteException ex) {
            ex.printStackTrace();
            return ex.getMessage();
        }

    }

    /**
     * Deletes all the images associated with this lixeira, the web service doesn't
     * support deleting one by one.
     * @param app the app key
     * @return null if it worked or the error message
     */
    public String deleteImages(String app) {

        try {
            SpottingSoap_Stub service = new SpottingSoap_Stub();
            OperationStatus ops = service.deleteAllMediaObjects(getGuid(), app);

            if (ops.isOperationSuceeded()) {
                return null;
            } else {
                return ops.getErrorMessage();
            }

        } catch (RemoteException ex) {
            ex.printStackTrace();
            return ex.getMessage();
        }

    }

    /**
     * Gets the complete data for this Lixeira from the server and stores it in the
     * bs var.
     * @param app the app key
     * @return null if it worked or the error message
     */
    public String getDataFromServer(String app) {
        SpottingSoap_Stub service = new SpottingSoap_Stub();
        try {
            bs = service.getBlackSpot(getGuid(), app);
            if (bs == null) {
                return "Error while getting data from server!";
            }
            System.out.println("Number of Classes recived from server: " + bs.getClassification().length);
            for (int i = 0; i < bs.getClassification().length; i++) {
                System.out.println("Class: " + bs.getClassification()[i]);
            }
            setState(getBs().getStatus().getValue());
            ArrayOfMediaReader ims = service.getAllMediaObjects(getGuid(), app);

            //DEBUG
            if (ims == null){
                System.out.println("IMS NULL");
            }
            else if (ims.getMediaReader() == null){
                System.out.println("Media REader null");
            }else{
                System.out.println("Length: "+ims.getMediaReader().length);
            }


            if (ims != null && ims.getMediaReader() != null && ims.getMediaReader().length > 0) {
            }
            if (ims != null && ims.getMediaReader() != null && ims.getMediaReader().length > 0) {
                System.out.println("Number of Photos recieved: " + ims.getMediaReader().length);
                imagesURLs = new ImageURL[ims.getMediaReader().length];
                for (int i = 0; i < ims.getMediaReader().length; i++) {
                    System.out.println("Photo title: " + ims.getMediaReader()[i].getTitle());
                    System.out.println("Photo title: " + ims.getMediaReader()[i].getUrl());
                    imagesURLs[i] = new ImageURL(ims.getMediaReader()[i]);

                }
            } else {

                imagesURLs = new ImageURL[0];

            }
            return null;
        } catch (RemoteException ex) {
            ex.printStackTrace();
            return ex.getMessage();
        }


    }

    /**
     * Static method to get all the lixeira near the given position
     * @param distanceInMeters the distance (it's a square area)
     * @param latitude the latitude of the position
     * @param longitude the longitude of the position
     * @param app the app key
     * @return
     */
    public static LixeiraSent[] getAllWithinDistance(double distanceInMeters, double latitude,
            double longitude, String app) {

        SpottingSoap_Stub service = new SpottingSoap_Stub();

        LixeiraSent[] lixeiras = null;

        try {
            ArrayOfBlackSpot abs = service.getAllSpotsWithinDistance(distanceInMeters,
                    latitude, longitude, app);

            if (abs.getBlackSpot() == null) {
                return null;
            }

            BlackSpot[] bsv = abs.getBlackSpot();

            lixeiras = new LixeiraSent[bsv.length];

            for (int i = 0; i < bsv.length; i++) {
                lixeiras[i] = new LixeiraSent(bsv[i]);
            }

        } catch (RemoteException ex) {
            ex.printStackTrace();
            return null;
        }

        return lixeiras;
    }
    /**
     * Static method to get all the lixeira which state is still pending
     * @param app the app key
     * @return
     */
    public static LixeiraSent[] getAllPending(String app) {

        SpottingSoap_Stub service = new SpottingSoap_Stub();

        LixeiraSent[] lixeiras = null;

        try {
            ArrayOfBlackSpot abs = service.getPendingBlackSpots(app);

            if (abs.getBlackSpot() == null) {
                return null;
            }

            BlackSpot[] bsv = abs.getBlackSpot();

            lixeiras = new LixeiraSent[bsv.length];

            for (int i = 0; i < bsv.length; i++) {
                lixeiras[i] = new LixeiraSent(bsv[i]);
            }

        } catch (RemoteException ex) {
            ex.printStackTrace();
            return null;
        }

        return lixeiras;
    }

    /**
     * Changes the state of the lixeira and automaticly commits it
     * @param newState the state to be changed into
     * @param app the app key
     * @return the lixeira in the ChangedState mode if the operation didnt work
     */
    public LixeiraChangedState changeState(BlackSpotState newState, String app) {

        LixeiraChangedState lix = new LixeiraChangedState(getGuid(),
                getTitle(), newState.getValue());

        LixeiraSendResult res = lix.send(app);
        System.out.println("App: " + app);
        if (!res.wasSuceded()) {
            synced = false;
            return lix;
        } else {
            setState(newState.getValue());
            return null;
        }

    }

    /**
     * Changes the state of the lixeira and doesnt automaticly commits it
     * @param newState the state to be changed into
     * @param app the app key
     * @return the lixeira in the ChangedState mode
     */
    public LixeiraChangedState changeState(String newState) {
        synced = false;
        return new LixeiraChangedState(getGuid(),
                getTitle(), newState);


    }

    /**
     * Synchronises the state with the server
     * @param app
     * @return
     */
    public boolean syncState(String app) {
        SpottingSoap_Stub service = new SpottingSoap_Stub();
        try {
            BlackSpot bsTemp = service.getBlackSpot(getGuid(), app);
            setState(bsTemp.getStatus().getValue());
        } catch (RemoteException ex) {
            ex.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * @return the synced
     */
    public boolean isSynced() {
        return synced;
    }

    /**
     * @param synced the synced to set
     */
    public void setSynced(boolean synced) {
        this.synced = synced;
    }

    /**
     * @return the bs
     */
    public BlackSpot getBs() {
        return bs;
    }

    /**
     * @return the images titles or null if non exist
     */
    public String[] getImagesTitles() {
        if (imagesURLs == null) {
            System.out.println("Should be init");
            return null;
        }
        if (imagesURLs.length == 0) {
            return null;
        }
        String[] titles = new String[imagesURLs.length];
        for (int i = 0; i < imagesURLs.length; i++) {
            titles[i] = imagesURLs[i].getTitle();
            System.out.println("URL: "+imagesURLs[i].getURL());
        }
        return titles;
    }
}
